package com.example.demo_mysql_mybatisplus.util;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author chenjb
 * @version 1.0
 * Create by 2023/4/7 18:40
 */
@Component
public class SqlMapperUtil {
    /**
     * 泛型类与其对应的baseMappe Bean的映射
     *  */
    private static final Map<String,BaseMapper> mapperMap= new HashMap<String,BaseMapper>();

    @Resource
    private void setBaseMappers(List<BaseMapper> baseMappers) {
        if(CollUtil.isNotEmpty(baseMappers)){
            for (BaseMapper proxy : baseMappers) {
                Class proxyed = (Class)proxy.getClass().getGenericInterfaces()[0];
                Type[] genericInterfaces = proxyed.getGenericInterfaces();
                ParameterizedType type = (ParameterizedType) genericInterfaces[0];
                Class cls = (Class) type.getActualTypeArguments()[0];
                if (cls.isAnnotationPresent(TableName.class)){
                    mapperMap.put(cls.getName(),proxy);
                }
            }
        }
    }

    /**
     * 获取mapper
     * @author chenjb
     * @date 2023/4/7 18:43
     * @param
     * @return com.baomidou.mybatisplus.core.mapper.BaseMapper
     */
    public static BaseMapper getMapper(Class clazz){
        return mapperMap.get(clazz.getName());
    }

    /**
     * 默认的通过id更新实体
     */
    public static <T> int updateById(T entity) {
        return getMapper(entity.getClass()).updateById(entity);
    }

    /**
     * 通过id更新实体，允许更新为null的字段值
     */
    public static <T> int updateByIdAllowNull(T entity , String... ignoreFields) {
        List<String> ignoreList = Arrays.asList(ignoreFields);
        Object idVal = null;
        UpdateWrapper<T> updateWrapper = new UpdateWrapper<>();
        List<Field> allFields = TableInfoHelper.getAllFields(entity.getClass());
        MetaObject metaObject = SystemMetaObject.forObject(entity);
        for (Field field : allFields) {
            if ( !ignoreList.contains(field.getName())) {
                Object value = metaObject.getValue(field.getName());
                updateWrapper.set(StringUtils.camelToUnderline(field.getName()), value);
                if("id".equals(field.getName())) idVal = value;
            }
        }
        updateWrapper.eq("id",idVal);
        return getMapper(entity.getClass()).update(null,updateWrapper);
    }

    /**
     * 通过 实体 获取 LambdaUpdateWrapper
     */
    public static <T> LambdaUpdateWrapper<T> getUpdateWrapper(T entity , String... ignoreFields) {
        List<String> ignoreList = ignoreFields==null?null:Arrays.asList(ignoreFields);

        UpdateWrapper<T> updateWrapper = new UpdateWrapper<>();
        List<Field> allFields = TableInfoHelper.getAllFields(entity.getClass());
        MetaObject metaObject = SystemMetaObject.forObject(entity);
        for (Field field : allFields) {
            if ( ignoreFields == null || !ignoreList.contains(field.getName())) {
                Object value = metaObject.getValue(field.getName());
                updateWrapper.set(StringUtils.camelToUnderline(field.getName()), value);
            }
        }
        return updateWrapper.lambda();
    }

}